package ia;

import java.util.Arrays;

/**
 * @author JFM
 */
public class Poblacion
	{
	private Distribucion[] distribuciones;

	public Poblacion(int cantidad)
		{
		distribuciones = new Distribucion[cantidad];
		for(int i=0; i<cantidad; i++)
			{
			Distribucion d;
			do{ d = new Distribucion(); }while(estaAgregado(d));
			
			distribuciones[i] = d;
			}
		Arrays.sort(distribuciones);
		}

	public Distribucion getSuperior()
		{ return distribuciones[0]; }

	public boolean estaAgregado(Distribucion d)
		{ return estaAgregado(d, distribuciones.length); }

	public boolean estaAgregado(Distribucion d, int corte)
		{
		for(int i=0; i<corte; i++)
			{ if(distribuciones[i] != null && distribuciones[i].getFitness() == d.getFitness()) return true; }
		return false;
		}

	public void evolucionar(int iteraciones, float tasaMortalidad, float tasaMutacion, float tasaReproduccion)
		{ 
		for(int i=0; i<iteraciones; i++)
			{
			// Determino a partir de que posicion en el array debo sobreescribir las distribuciones.
			int corte = (int) (distribuciones.length * tasaMortalidad);

			// Determino la cantidad de reproducciones y de mutaciones.
			for(int r=corte; r<distribuciones.length; r++)
				{
				float ran = (float) Math.random();

				if(ran <= tasaMutacion) { distribuciones[r].rehacer(); } else
				if(ran <= tasaMutacion+tasaReproduccion) { distribuciones[r].mutar(getDistribucionAleatoria(corte)); } else
					{ distribuciones[r].cruzar(getDistribucionAleatoria(corte), getDistribucionAleatoria(corte)); }

				while( estaAgregado(distribuciones[r], r) ) { distribuciones[r].rehacer();}
				}

			Arrays.sort(distribuciones);
			}
		}

	public Distribucion getDistribucionAleatoria(int corte)
		{
		int ran = (int) ( Math.random()*(corte-1) );
		return distribuciones[ran];
		}

	public static void main(String[] args)
		{
		Poblacion pob = new Poblacion(250);
		float mortalidad = 0.6f;
		float reproduccion = 0.15f;
		float mutaciones = 0.15f;

		for(int k=0; k<6; k++)
			{
			pob.evolucionar(200, mortalidad, reproduccion, mutaciones);
			System.out.println(pob.getSuperior().getFitness());
			}
		}
	}
